# utils/report_utils.py
import os
import subprocess
import getpass
from datetime import datetime
import pytest
import allure
from allure_commons.types import AttachmentType


class AllureReportManager:
    def __init__(self, base_dir="/Users/siyiyi/automation_-interface_testing/allures"):
        self.base_dir = base_dir
        self.results_dir = os.path.join(base_dir, "temp_results")
        self.reports_dir = os.path.join(base_dir, "html_reports")

        # 创建必要目录
        os.makedirs(self.results_dir, exist_ok=True)
        os.makedirs(self.reports_dir, exist_ok=True)

    def get_caller_info(self, caller_name=None):
        """获取调用者信息"""
        try:
            username = getpass.getuser()
            timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
            actual_caller = caller_name or username
            return actual_caller, timestamp
        except Exception:
            return "unknown_user", datetime.now().strftime("%Y%m%d_%H%M%S")

    def generate_report_path(self, caller_name=None):
        """生成报告路径"""
        caller, timestamp = self.get_caller_info(caller_name)
        report_dir_name = f"{caller}_report_{timestamp}"
        return os.path.join(self.reports_dir, report_dir_name)

    def run_pytest_with_allure(self, test_path="tests", caller_name=None, markers=None):
        """使用pytest运行测试并生成Allure报告"""

        report_path = self.generate_report_path(caller_name)
        caller, timestamp = self.get_caller_info(caller_name)

        print(f"🔧 开始生成测试报告 - 调用者: {caller}")
        print(f"📁 结果目录: {self.results_dir}")
        print(f"📊 报告目录: {report_path}")

        # 清理临时目录
        self.clean_directory(self.results_dir)

        # 构建pytest命令
        pytest_cmd = [
            "pytest", test_path,
            "-v",
            "--tb=short",
            f"--alluredir={self.results_dir}",
            "--clean-alluredir"
        ]

        # 添加marker过滤
        if markers:
            pytest_cmd.extend(["-m", markers])

        print(f"🚀 执行命令: {' '.join(pytest_cmd)}")

        # 运行pytest测试
        try:
            result = subprocess.run(pytest_cmd, capture_output=True, text=True)

            if result.returncode not in [0, 1, 5]:  # 0:成功, 1:失败, 5:无测试用例
                print(f"❌ pytest执行失败: {result.stderr}")
                return None

            # 生成Allure HTML报告
            return self.generate_allure_report(report_path, caller)

        except Exception as e:
            print(f"❌ 执行测试时发生错误: {e}")
            return None

    def generate_allure_report(self, report_path, caller_name):
        """生成Allure HTML报告"""
        allure_cmd = [
            "allure", "generate",
            self.results_dir,
            "-o", report_path,
            "--clean"
        ]

        print(f"📊 生成HTML报告: {' '.join(allure_cmd)}")

        try:
            result = subprocess.run(allure_cmd, capture_output=True, text=True)

            if result.returncode == 0:
                print(f"✅ Allure报告生成成功!")
                print(f"📊 报告路径: {report_path}")
                print(f"🌐 查看报告: file://{report_path}/index.html")

                # 添加环境信息
                self.add_environment_info(report_path, caller_name)
                return report_path
            else:
                print(f"❌ Allure报告生成失败: {result.stderr}")
                return None

        except Exception as e:
            print(f"❌ 生成Allure报告时发生错误: {e}")
            return None

    def add_environment_info(self, report_path, caller_name):
        """添加环境信息到报告"""
        try:
            env_file = os.path.join(report_path, "environment.properties")
            with open(env_file, 'w', encoding='utf-8') as f:
                f.write(f"执行人={caller_name}\n")
                f.write(f"执行时间={datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\n")
                f.write(f"报告路径={report_path}\n")
        except Exception as e:
            print(f"⚠️ 添加环境信息失败: {e}")

    def clean_directory(self, directory):
        """清理目录"""
        import shutil
        if os.path.exists(directory):
            shutil.rmtree(directory)
        os.makedirs(directory)

    def open_report_in_browser(self, caller_name=None):
        """在浏览器中打开最新报告"""
        try:
            if caller_name:
                # 查找指定调用者的最新报告
                pattern = f"{caller_name}_report_*"
                matching_dirs = [d for d in os.listdir(self.reports_dir)
                                 if d.startswith(caller_name + "_report_")]
            else:
                # 查找所有报告中的最新一个
                matching_dirs = [d for d in os.listdir(self.reports_dir)
                                 if d.endswith("_report_")]

            if not matching_dirs:
                print("❌ 未找到测试报告")
                return

            latest_report = sorted(matching_dirs)[-1]
            report_dir = os.path.join(self.reports_dir, latest_report)
            index_file = os.path.join(report_dir, "index.html")

            if os.path.exists(index_file):
                import webbrowser
                webbrowser.open(f"file://{index_file}")
                print(f"🌐 在浏览器中打开报告: {index_file}")
            else:
                print("❌ 报告文件不存在")

        except Exception as e:
            print(f"❌ 打开报告时发生错误: {e}")


# 创建全局实例
report_manager = AllureReportManager()